import { JobStatus } from '../type';
import { agentConfig } from '$domain/model/agent/config';
import { GlobalBuses } from '$domain/service/eventBus';
import { SimJobStatus } from '../type';
import { reportService } from '../service/reportService';
import { FinishingState } from './finishingState';
import { SimulationWatcher } from '../simulationWatcher';
import { DriverReleasedEvent } from '$domain/event';
import { BaseSimulationJobState } from './baseJobState';
import { ICommandExecutor, ExecutedResult } from '$domain/service/commandLineExecutor';
import { DriverRunCommand, DriverRunOptions } from '$domain/model/driver';
export class RunningState extends BaseSimulationJobState {

  private _commandExecutor: ICommandExecutor;

  constructor() { super('RunningState'); }

  async doRun() {

    this.simJobRepo.updateJobStatus(this.jobId, JobStatus.Runing);
    await reportService.jobStatusReport(this.jobId, SimJobStatus.Running);

    if (agentConfig.ossPolicy === 'driver-run-only') {
      this.logger.enableOSS();
    }

    const driverRunOptions: DriverRunOptions = {
      logger: this.logger,
      driverName: this.product,
      configFilePath: this.simulationPath.getSimInputFile(),
      outputFilePath: this.simulationPath.getSimOutputFile()
    };
 
    const driverRunCommand = this._commandExecutor = new DriverRunCommand(driverRunOptions);

    let executeResult: ExecutedResult;
    let simWatcher = new SimulationWatcher();
    try {
      simWatcher.setWatchDirectory(this.simulationPath.getSimWatchDir());
      simWatcher.setMountPath(this.storagePath.getSimSyncPath(this.jobId));
      simWatcher.start();
      executeResult = await driverRunCommand.execute();
    } catch (e) {
      this.logger.error(`😫 Job(jobId=${this.jobId}) execution failed, e: ${e.message}`);
      throw e;
    } finally {
      if (agentConfig.ossPolicy === 'driver-run-only') {
        this.logger.disableOSS();
      }
      simWatcher.stop();
      GlobalBuses.DriverEvent.publish(DriverReleasedEvent.NAME, new DriverReleasedEvent(this.product));
    }

    this.simJobRepo.updateBySelective(this.jobId, {
      processId: executeResult.pid,
      exitCode: executeResult.exitCode,
      exitMessage: executeResult.errorMsg
    });

    await this.doNextStateOperation(new FinishingState());
  }

  async doCancel() {
    this.logger.debug('🙅‍♂️ postCancel executing....');
    if (this._commandExecutor) {
      this._commandExecutor.terminate(true);
    }
  }
}